package com.webrtc.demo

import android.app.Application
import android.util.Log
import com.webrtc.demo.call.*
import com.webrtc.demo.util.logD
import org.webrtc.*
import java.nio.ByteBuffer

object ConnectionManager {

    val rootEglBase = EglBase.create()
    private lateinit var peerConnectionFactory: PeerConnectionFactory

    private val connMap = mutableMapOf<String, Connection>()

    // private val mediaConnMap = mutableMapOf<String, MediaConnection>()
    private var videoCallListeners =
        mutableListOf<(callerUid: String, cId: String?) -> Boolean>()// return true，表示已处理；cId为空表示是单人视频聊天

    fun init(context: Application) {
        if (ConnectionManager::peerConnectionFactory.isInitialized) {
            return
        }

        val encoderFactory: VideoEncoderFactory
        val decoderFactory: VideoDecoderFactory
        encoderFactory = DefaultVideoEncoderFactory(
            rootEglBase.eglBaseContext, false /* enableIntelVp8Encoder */, true
        )
        decoderFactory = DefaultVideoDecoderFactory(rootEglBase.eglBaseContext)
        PeerConnectionFactory.initialize(
            PeerConnectionFactory.InitializationOptions.builder(context)
                .setEnableInternalTracer(true)
                .createInitializationOptions()
        )
        val builder = PeerConnectionFactory.builder()
            .setVideoEncoderFactory(encoderFactory)
            .setVideoDecoderFactory(decoderFactory)
        builder.setOptions(null)
        peerConnectionFactory = builder.createPeerConnectionFactory()

        RTCSignalClient.addOnSignalEventListener(object : OnSignalEventListener {
            override fun onRoomNegotiate(
                uid: String,
                roomid: String,
                type: RoomNegotiate
            ): Boolean {
                if (type == RoomNegotiate.ROOM_CALL) {// ROOM_CALL 类型的全部在此处处理
                    videoCallListeners.forEach {
                        if (it(uid, roomid)) return@forEach
                    }
                    return true
                }

                return super.onRoomNegotiate(uid, roomid, type)
            }

            override fun onNegotiate(uid: String, type: Negotiate): Boolean {
                if (type == Negotiate.CALL) {// CALL 类型的全部在此处处理
                    videoCallListeners.forEach {
                        if (it(uid, null)) return@forEach
                    }
                    return true
                }

                return false
            }

            override fun onOffer(
                uid: String,
                sdp: String,
                mediaType: MediaType,
                roomid: String?
            ): Boolean {
                // 只处理一对一文本类型的，其他类型不处理
                return if (mediaType == MediaType.DATA && roomid == null) {
                    get(uid).onOffer(SessionDescription(SessionDescription.Type.OFFER, sdp))
                    true
                } else {
                    false
                }
            }

            override fun onAnswer(
                uid: String,
                sdp: String,
                mediaType: MediaType,
                roomid: String?
            ): Boolean {
                // 只处理一对一文本类型的，其他类型不处理
                return if (mediaType == MediaType.DATA && roomid == null) {
                    // offer才触发新连接的创建，其它类型会忽略
                    return getCache(uid)?.let {
                        it.onAnswer(SessionDescription(SessionDescription.Type.ANSWER, sdp))
                        true
                    } ?: false
                } else {
                    false
                }
            }

            override fun onCandidate(
                uid: String,
                ice: IceCandidate,
                mediaType: MediaType,
                roomid: String?
            ): Boolean {
                // 只处理一对一文本类型的，其他类型不处理
                return if (mediaType == MediaType.DATA && roomid == null) {
                    return getCache(uid)?.let {
                        it.onIceCandidate(ice, true)
                        true
                    } ?: false
                } else {
                    false
                }
            }
        })
    }

    fun addOnVideoCallListener(listener: (String, String?) -> Boolean) {
        videoCallListeners.add(listener)
    }

    fun removeVideoCallListener(listener: (String, String?) -> Boolean) {
        videoCallListeners.remove(listener)
    }

    private fun getCache(uid: String): Connection? {
        checkNotBlank(uid)
        return connMap[uid]
    }

    fun get(uid: String): Connection {
        checkNotBlank(uid)

        val result = if (connMap.containsKey(uid)) connMap[uid]
        else {
            synchronized(connMap) {
                if (connMap.containsKey(uid)) connMap[uid]
                else {
                    Connection(uid, peerConnectionFactory).also { connMap[uid] = it }
                }
            }
        }

        checkNotNull(result)

        return result
    }

    fun getMedia(uid: String): MediaConnection {
        checkNotBlank(uid)

//        val result = if (mediaConnMap.containsKey(uid)) mediaConnMap[uid]
//        else {
//            synchronized(mediaConnMap) {
//                if (mediaConnMap.containsKey(uid)) mediaConnMap[uid]
//                else {
        return MediaConnection(uid, peerConnectionFactory)
//                }
//            }
//        }

//        checkNotNull(result)

//        return result
    }

    fun getMedia(uid: String, videoTrack: VideoTrack, audioTrack: AudioTrack): MediaConnection {
        return MediaConnection(uid, peerConnectionFactory, videoTrack, audioTrack)
    }

    internal fun remove(connection: Connection) {
        connMap.remove(connection.uid)
    }

//    internal fun remove(connection: MediaConnection) {
//        mediaConnMap.remove(connection.uid)
//    }

    private fun checkNotBlank(s: String) {
        if (s.isBlank()) {
            throw RuntimeException("uid 不能为空")
        }
    }

}

/**
 * @param uid peer对等方的唯一id
 */
class Connection internal constructor(
    val uid: String,
    peerConnectionFactory: PeerConnectionFactory
) {

    private var peerConnection: PeerConnection

    var cId: String? = null

    val connectionState: PeerConnection.PeerConnectionState
        get() = peerConnection.connectionState()

    private var dataChannel: DataChannel

    private val peerConnectionObserver: PeerConnection.Observer = object : PeerConnection.Observer {
        override fun onIceCandidate(p0: IceCandidate?) {
            if (p0 != null) {
                logD(TAG, "$uid 搜寻到候选人")
                RTCSignalClient.sendCandidate(
                    uid,
                    p0.sdp,
                    p0.sdpMid,
                    p0.sdpMLineIndex,
                    MediaType.DATA,
                    roomid = cId
                ) {
                    logD(TAG, "Candidate 信令发送至 $uid 成功")
                }
            }
        }

        override fun onDataChannel(p0: DataChannel?) {
            logD(TAG, "$uid onDataChannel")
        }

        override fun onIceConnectionReceivingChange(p0: Boolean) {
            logD(TAG, "$uid onIceConnectionReceivingChange")
        }

        override fun onIceConnectionChange(p0: PeerConnection.IceConnectionState?) {
            if (p0 != null) {
                logD(TAG, "$uid onIceConnectionChange $p0")
            }
        }

        override fun onIceGatheringChange(p0: PeerConnection.IceGatheringState?) {
            if (p0 != null) {
                logD(TAG, "$uid onIceGatheringChange $p0")
            }
        }

        override fun onAddStream(p0: MediaStream?) {
            logD(TAG, "$uid onAddStream")
        }

        override fun onSignalingChange(p0: PeerConnection.SignalingState?) {
            logD(TAG, "$uid onSignalingChange")
        }

        override fun onIceCandidatesRemoved(p0: Array<out IceCandidate>?) {
            if (p0 != null) {
                logD(TAG, "$uid onIceCandidatesRemoved $p0")
            }
            // todo remove
        }

        override fun onConnectionChange(newState: PeerConnection.PeerConnectionState?) {
            super.onConnectionChange(newState)
            newState?.let {
                connectionStateListeners.forEach { it.onConnectState(newState) }
            }
        }

        override fun onRemoveStream(p0: MediaStream?) {
            logD(TAG, "$uid onRemoveStream")
        }

        override fun onRenegotiationNeeded() {
            logD(TAG, "$uid onRenegotiationNeeded")
        }

        override fun onAddTrack(p0: RtpReceiver?, p1: Array<out MediaStream>?) {
            logD(TAG, "$uid onAddTrack")
        }
    }

    private val dataChannelObserver = object : DataChannel.Observer {
        override fun onMessage(buffer: DataChannel.Buffer) {
            val bytes: ByteArray = if (buffer.data.hasArray()) {
                buffer.data.array()
            } else {
                ByteArray(buffer.data.remaining())
            }
            buffer.data.get(bytes)
            val str = String(bytes)
            logD(TAG, "收到 $uid 发送的文本：$str")
            textStation.onReceive(str)
        }

        override fun onBufferedAmountChange(p0: Long) {
        }

        override fun onStateChange() {
            dataChannelState()
        }
    }

    private fun dataChannelState() {
        logD(TAG, "text channel state:${dataChannel.state()}")

//        if (dataChannel.state() == DataChannel.State.OPEN)
//            textStation.send("发给 $uid ，现在时间 ${System.currentTimeMillis()}")
    }

    val textStation: TextStation = TextStation()

    private val connectionStateListeners = mutableListOf<ConnectionStateListener>()

    private var closed: Boolean = false

    init {
        peerConnection =
            peerConnectionFactory.createPeerConnection(getIceConfig(), peerConnectionObserver)
                ?: throw RuntimeException("createPeerConnection 失败")

        val init = DataChannel.Init()
        init.id = 1
        init.ordered = true
        init.negotiated = true
        init.maxRetransmits = -1
        init.maxRetransmitTimeMs = -1
        dataChannel = peerConnection.createDataChannel("test", init)
        dataChannel.registerObserver(dataChannelObserver)
    }

    fun connect() {
        if (closed) throw RuntimeException("Connection 已被关闭")

        val mediaConstraints = MediaConstraints()
        peerConnection.createOffer(object : SimpleSdpObserver() {
            override fun onCreateSuccess(sessionDescription: SessionDescription) {
                peerConnection.setLocalDescription(SimpleSdpObserver(), sessionDescription)
                RTCSignalClient.sendOffer(
                    uid,
                    sessionDescription.description,
                    MediaType.DATA,
                    roomid = cId
                ) {
                    logD(TAG, "$uid offer 信令发送至 $uid 成功")
                }
            }

            override fun onCreateFailure(msg: String) {
                super.onCreateFailure(msg)
                Log.i(TAG, "$uid Create offer failure !")
            }
        }, mediaConstraints)
    }

    fun close() {
        closed = true

        ConnectionManager.remove(this)

        dataChannel.close()
        textStation.close()

        peerConnection.close()
        connectionStateListeners.clear()
    }

    internal fun onOffer(offer: SessionDescription) {
        logD(TAG, "$uid 接收到 offer")

        peerConnection.setRemoteDescription(object : SimpleSdpObserver() {
            override fun onSetFailure(msg: String) {
                super.onSetFailure(msg)
                Log.i(TAG, "$uid set remote offer failure !")
                // connectionStateListeners.forEach { it.onConnectFailure() }
            }
        }, offer)

        val sdpMediaConstraints = MediaConstraints()
        peerConnection.createAnswer(object : SimpleSdpObserver() {
            override fun onCreateSuccess(sessionDescription: SessionDescription) {
                Log.i(TAG, "Create answer success !")
                peerConnection.setLocalDescription(
                    SimpleSdpObserver(),
                    sessionDescription
                )

                RTCSignalClient.sendAnswer(
                    uid,
                    sessionDescription.description,
                    MediaType.DATA,
                    roomid = cId
                ) {
                    logD(TAG, "answer 信令发送至 $uid 成功")
                }
            }

            override fun onCreateFailure(msg: String) {
                super.onCreateFailure(msg)
                Log.i(TAG, "$uid Create answer failure !")
            }
        }, sdpMediaConstraints)
    }

    internal fun onAnswer(answer: SessionDescription) {
        logD(TAG, "$uid 接收到 answer")

        peerConnection.setRemoteDescription(object : SimpleSdpObserver() {
            override fun onSetFailure(msg: String) {
                super.onSetFailure(msg)
                // connectionStateListeners.forEach { it.onConnectFailure() }
            }
        }, answer)
    }

    internal fun onIceCandidate(ice: IceCandidate, add: Boolean) {
        if (add) {
            peerConnection.addIceCandidate(ice)
        } else peerConnection.removeIceCandidates(arrayOf(ice))
    }

    // states
    fun registerConnectionStatusListener(listener: ConnectionStateListener) {
        connectionStateListeners.add(listener)
    }

    fun unregisterConnectionStatusListener(listener: ConnectionStateListener) {
        connectionStateListeners.remove(listener)
    }


    companion object {
        private const val TAG = "Connection"
    }

    inner class TextStation {
        private val listeners = mutableListOf<(String) -> Unit>()

        fun registerListener(listener: (String) -> Unit) {
            listeners.add(listener)
        }

        fun unregisterListener(listener: (String) -> Unit): Boolean =
            listeners.remove(listener)

        internal fun onReceive(msg: String) {
            listeners.forEach { it(msg) }
        }

        fun send(msg: String): Boolean =
            dataChannel.send(DataChannel.Buffer(ByteBuffer.wrap(msg.toByteArray()), false))

        internal fun close() {
            listeners.clear()
        }
    }
}

class MediaConnection internal constructor(
    val uid: String,
    peerConnectionFactory: PeerConnectionFactory,
    videoTrack: VideoTrack? = null,
    audioTrack: AudioTrack? = null
) {

    /**
     * 因为次constructor方法在init方法之后执行，所以_localVideoTrack在init时还未赋值，导致代码逻辑异常，
     * 先改为全部由主constructor传参
     */
//class MediaConnection internal constructor(
//    val uid: String,
//    peerConnectionFactory: PeerConnectionFactory
//) {
//    constructor(
//        uid: String,
//        peerConnectionFactory: PeerConnectionFactory, videoTrack: VideoTrack, audioTrack: AudioTrack
//    ) : this(uid, peerConnectionFactory) {
//        _localVideoTrack = videoTrack
//        _localAudioTrack = audioTrack
//    }

    private var peerConnection: PeerConnection

    var cId: String? = null

    val connectionState: PeerConnection.PeerConnectionState
        get() = peerConnection.connectionState()

    private fun sendIceCandidate(ice: IceCandidate) {
        RTCSignalClient.sendCandidate(
            uid,
            ice.sdp,
            ice.sdpMid,
            ice.sdpMLineIndex,
            MediaType.VIDEO,
            roomid = cId
        ) {
            logD(TAG, "Candidate 信令发送至 $uid 成功")
        }
    }

    private val peerConnectionObserver: PeerConnection.Observer = object : PeerConnection.Observer {
        override fun onIceCandidate(p0: IceCandidate?) {
            if (p0 != null) {
                logD(TAG, "$uid 搜寻到候选人")
                if (enableExchangeIceCandidate)
                    sendIceCandidate(p0)
                else localIceCandidateCache.add(p0)
            }
        }

        override fun onDataChannel(p0: DataChannel?) {
            logD(TAG, "$uid onDataChannel")
        }

        override fun onIceConnectionReceivingChange(p0: Boolean) {
            logD(TAG, "$uid onIceConnectionReceivingChange")
        }

        override fun onIceConnectionChange(p0: PeerConnection.IceConnectionState?) {
            if (p0 != null) {
                logD(TAG, "$uid onIceConnectionChange $p0")
            }
        }

        override fun onIceGatheringChange(p0: PeerConnection.IceGatheringState?) {
            if (p0 != null) {
                logD(TAG, "$uid onIceGatheringChange $p0")
            }
        }

        override fun onAddStream(p0: MediaStream?) {
            logD(TAG, "$uid onAddStream")
        }

        override fun onSignalingChange(p0: PeerConnection.SignalingState?) {
            logD(TAG, "$uid onSignalingChange")
        }

        override fun onIceCandidatesRemoved(p0: Array<out IceCandidate>?) {
            if (p0 != null) {
                logD(TAG, "$uid onIceCandidatesRemoved $p0")
            }
            // todo remove
        }

        override fun onConnectionChange(newState: PeerConnection.PeerConnectionState?) {
            super.onConnectionChange(newState)
            newState?.let {

                when (it) {
                    PeerConnection.PeerConnectionState.CLOSED -> {
                        logD(TAG, "$uid 对方已挂断")
                    }
                    PeerConnection.PeerConnectionState.FAILED -> {
                        logD(TAG, "$uid 连接失败")
                    }
                    PeerConnection.PeerConnectionState.CONNECTED -> {
                        logD(TAG, "$uid 连接成功")
                    }
                    PeerConnection.PeerConnectionState.DISCONNECTED -> {
                        logD(TAG, "$uid 连接中断")
                    }
                }

                connectionStateListeners.forEach { it.onConnectState(newState) }
            }
        }

        override fun onRemoveStream(p0: MediaStream?) {
            logD(TAG, "$uid onRemoveStream")
        }

        override fun onRenegotiationNeeded() {
            logD(TAG, "$uid onRenegotiationNeeded")
        }

        override fun onAddTrack(p0: RtpReceiver?, p1: Array<out MediaStream>?) {
            logD(TAG, "$uid onAddTrack")

            val track = p0?.track()
            if (track is VideoTrack) {
                logD(TAG, "onAddVideoTrack")
                remoteVideoTrack = track
                bindRemoteVideo()
            }
        }
    }

    private lateinit var _localVideoTrack: VideoTrack
    val localVideoTrack
        get() = _localVideoTrack
    private lateinit var _localAudioTrack: AudioTrack
    val localAudioTrack
        get() = _localAudioTrack

    private var remoteSurfaceView: SurfaceViewRenderer? = null
    val pRemoteSurfaceView
        get() = remoteSurfaceView

    private var remoteVideoTrack: VideoTrack? = null

    private fun bindRemoteVideo() {
        val _remoteVideoTrack = remoteVideoTrack
        val _remoteSurfaceView = remoteSurfaceView

        if (_remoteVideoTrack != null && _remoteSurfaceView != null) {
            _remoteVideoTrack.setEnabled(true)
            val videoSink = ProxyVideoSink()
            videoSink.setTarget(_remoteSurfaceView)
            _remoteVideoTrack.addSink(videoSink)
        }
    }

    private val connectionStateListeners = mutableListOf<ConnectionStateListener>()

    private var closed: Boolean = false

    private val videoSource: VideoSource?
    private val videoSink: ProxyVideoSink?

    init {
        videoTrack?.let { _localVideoTrack = it }
        audioTrack?.let { _localAudioTrack = it }

        if (!this::_localVideoTrack.isInitialized) {// video和audio同时设置，判断之一即可
            videoSource = peerConnectionFactory.createVideoSource(false)
//            mVideoCapturer.initialize(
//                mSurfaceTextureHelper,
//                applicationContext,
//                videoSource.capturerObserver
//            )
            _localVideoTrack = peerConnectionFactory.createVideoTrack(
                VIDEO_TRACK_ID,
                videoSource
            )
            _localVideoTrack.setEnabled(true)
            videoSink = ProxyVideoSink()
            _localVideoTrack.addSink(videoSink)

            val audioSource = peerConnectionFactory.createAudioSource(
                MediaConstraints()
            )
            _localAudioTrack = peerConnectionFactory.createAudioTrack(
                AUDIO_TRACK_ID,
                audioSource
            )
            _localAudioTrack.setEnabled(true)
        } else {
            videoSource = null
            videoSink = null
        }

        val constraints = MediaConstraints()
//        constraints.mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"))
//        constraints.mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"))
//        constraints.optional.add(MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"))

        peerConnection =
            peerConnectionFactory.createPeerConnection(
                getIceConfig(),
                constraints,
                peerConnectionObserver
            )
                ?: throw RuntimeException("createPeerConnection 失败")

        peerConnection.addTrack(_localVideoTrack)
        peerConnection.addTrack(_localAudioTrack)
    }

    private val remoteIceCandidateCache = mutableListOf<IceCandidate>()
    private val localIceCandidateCache = mutableListOf<IceCandidate>()

    private var enableExchangeIceCandidate = false

    fun setSurfaceViewRenderer(
        localSurfaceView: SurfaceViewRenderer?,
        remoteSurfaceView: SurfaceViewRenderer
    ) {
        videoSink?.setTarget(localSurfaceView)
        this.remoteSurfaceView = remoteSurfaceView
        bindRemoteVideo()
    }

    // 如使用次级构造器，此处返回null
    fun getCapturerObserver(): CapturerObserver? = videoSource?.capturerObserver

    fun connect() {
        if (closed) throw RuntimeException("Connection 已被关闭")

        val mediaConstraints = MediaConstraints()
        mediaConstraints.mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"))
        mediaConstraints.mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"))
        mediaConstraints.optional.add(MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"))

        peerConnection.createOffer(object : SimpleSdpObserver() {
            override fun onCreateSuccess(sessionDescription: SessionDescription) {
                peerConnection.setLocalDescription(SimpleSdpObserver(), sessionDescription)
                RTCSignalClient.sendOffer(
                    uid, sessionDescription.description, MediaType.VIDEO,
                    roomid = cId
                ) {
                    logD(TAG, "$uid offer 信令发送至 $uid 成功")
                }
            }

            override fun onCreateFailure(msg: String) {
                super.onCreateFailure(msg)
                logD(TAG, "$uid Create offer failure !")
            }
        }, mediaConstraints)
    }

    fun close() {
        closed = true

        // ConnectionManager.remove(this)

        // 由外界处理
        // PeerConnectionFactory.stopInternalTracingCapture()
        // PeerConnectionFactory.shutdownInternalTracer()

        peerConnection.close()
        connectionStateListeners.clear()
    }

    internal fun onOffer(offer: SessionDescription) {
        logD(TAG, "$uid 接收到 offer")

        peerConnection.setRemoteDescription(object : SimpleSdpObserver() {
            override fun onSetFailure(msg: String) {
                super.onSetFailure(msg)
                logD(TAG, "$uid set remote offer failure !")
                // connectionStateListeners.forEach { it.onConnectFailure() }
            }
        }, offer)

        val sdpMediaConstraints = MediaConstraints()
        peerConnection.createAnswer(object : SimpleSdpObserver() {
            override fun onCreateSuccess(sessionDescription: SessionDescription) {
                logD(TAG, "Create answer success !")
                peerConnection.setLocalDescription(
                    SimpleSdpObserver(),
                    sessionDescription
                )

                enableExchangeIceCandidate()

                RTCSignalClient.sendAnswer(
                    uid, sessionDescription.description, MediaType.VIDEO,
                    roomid = cId
                ) {
                    logD(TAG, "answer 信令发送至 $uid 成功")
                }
            }

            override fun onCreateFailure(msg: String) {
                super.onCreateFailure(msg)
                logD(TAG, "$uid Create answer failure !")
            }
        }, sdpMediaConstraints)
    }

    internal fun onAnswer(answer: SessionDescription) {
        logD(TAG, "$uid 接收到 answer")

        peerConnection.setRemoteDescription(object : SimpleSdpObserver() {
            override fun onSetFailure(msg: String) {
                super.onSetFailure(msg)
                // connectionStateListeners.forEach { it.onConnectFailure() }
            }

            override fun onSetSuccess() {
                super.onSetSuccess()
                enableExchangeIceCandidate()
            }
        }, answer)
    }

    private fun enableExchangeIceCandidate() {
        enableExchangeIceCandidate = true
        if (remoteIceCandidateCache.isNotEmpty()) {
            remoteIceCandidateCache.forEach {
                onIceCandidate(it, add = true)
            }
            remoteIceCandidateCache.clear()
        }

        if (localIceCandidateCache.isNotEmpty()) {
            localIceCandidateCache.forEach {
                sendIceCandidate(it)
            }
            localIceCandidateCache.clear()
        }
    }

    internal fun onIceCandidate(ice: IceCandidate, add: Boolean) {
        if (add) {
            if (enableExchangeIceCandidate)
                peerConnection.addIceCandidate(ice)
            else remoteIceCandidateCache.add(ice)
        } else peerConnection.removeIceCandidates(arrayOf(ice))
    }

    // states
    fun registerConnectionStatusListener(listener: ConnectionStateListener) {
        connectionStateListeners.add(listener)
    }

    fun unregisterConnectionStatusListener(listener: ConnectionStateListener) {
        connectionStateListeners.remove(listener)
    }


    class ProxyVideoSink : VideoSink {

        private var mTarget: VideoSink? = null

        @Synchronized
        override fun onFrame(frame: VideoFrame) {
            if (mTarget == null) {
                logD(TAG, "Dropping frame in proxy because target is null.")
                return
            }
            mTarget!!.onFrame(frame)
        }

        @Synchronized
        fun setTarget(target: VideoSink?) {
            mTarget = target
        }

    }

    companion object {
        private const val TAG = "MediaConnection"

        const val VIDEO_TRACK_ID = "ARDAMSv0"
        const val AUDIO_TRACK_ID = "ARDAMSa0"

    }
}

private fun getIceConfig() = PeerConnection.RTCConfiguration(
    mutableListOf(
        PeerConnection.IceServer("stun:stun.xten.com:3478"),
        PeerConnection.IceServer("stun:stun.ekiga.net"),
        PeerConnection.IceServer("stun:stun.ideasip.com"),
        PeerConnection.IceServer("stun:stun.schlund.de"),
        PeerConnection.IceServer("stun:stun.voiparound.com"),
        PeerConnection.IceServer("stun:relay.instant.io:3478?transport=udp")
    )
)

open class SimpleSdpObserver : SdpObserver {
    override fun onCreateSuccess(sessionDescription: SessionDescription) {
    }

    override fun onSetSuccess() {
    }

    override fun onCreateFailure(msg: String) {
    }

    override fun onSetFailure(msg: String) {
    }
}

interface ConnectionStateListener {
    fun onConnectState(state: PeerConnection.PeerConnectionState)
}